library(ggplot2)
library(readr)
chic <- read_csv("ggplot2/ggModify/chicago-nmmaps.csv")

# 1. 箱形图的替代方案
g <-
  ggplot(chic, aes(x = season, y = o3,
                   color = season)) +
    labs(x = "Season", y = "Ozone") +
    scale_color_brewer(palette = "Dark2", guide = "none")

g + geom_boxplot()

# 让我们画出原始数据的每个数据点:
g + geom_point()

# 试着给数据添加一点抖动。我喜欢这种可视化，但使用抖动时要小心，因为这是在故意给数据添加噪音，这可能会导致对数据的误解。
g + geom_jitter(width = .3, alpha = .5)

# 1.1 小提琴图
# 小提琴图是一种有用的可视化方法，它类似于箱形图，只是使用的是核密度来显示拥有最多数据的位置。
g + geom_violin(fill = "gray80", size = 1, alpha = .5)

# 我们当然可以将估算的密度和原始数据点结合起来:
g + geom_violin(fill = "gray80", size = 1, alpha = .5) +
    geom_jitter(alpha = .25, width = .3) +
    coord_flip()

# {ggforce}包提供了所谓的sina函数，其中抖动的宽度是由数据的密度分布控制的，这使得抖动在视觉上更吸引人:
library(ggforce)

g + geom_violin(fill = "gray80", size = 1, alpha = .5) +
    geom_sina(alpha = .25) +
    coord_flip()

# 为了便于估计分位数，我们还可以在小提琴中添加盒子图的盒子来表示25%-quartile、中位数和75%-quartile:
g + geom_violin(aes(fill = season), size = 1, alpha = .5) +
    geom_boxplot(outlier.alpha = 0, coef = 0,
                 color = "gray40", width = .2) +
    scale_fill_brewer(palette = "Dark2", guide = "none") +
    coord_flip()

# 2. Rug

# Rug代表单个数量变量的数据，显示为沿轴线的标记。
# 在大多数情况下，它是在散点图或热图之外使用的，以可视化一个或两个变量的总体分布:
ggplot(chic, aes(x = date, y = temp,
                 color = season)) +
  geom_point(show.legend = FALSE) +
  geom_rug(show.legend = FALSE) +
  labs(x = "Year", y = "Temperature (°F)")

ggplot(chic, aes(x = date, y = temp, color = season)) +
  geom_point(show.legend = FALSE) +
  geom_rug(sides = "r", alpha = .3, show.legend = FALSE) +
  labs(x = "Year", y = "Temperature (°F)")

# 3. 创建相关矩阵

# 有几个包可以创建相关矩阵图，有些基于{ggplot2}。下面展示如何在没有扩展包的情况下做到这一点。
# 第一步是创建相关矩阵。这里使用了{corrr}包，它可以很好地处理管道。
# 我们使用Pearson，因为所有的变量都是正态分布(但如果你的变量是其他分布，可以考虑Spearman)。
# 注意，由于相关矩阵有冗余信息，我们将其一半设置为NA。
corm <-
  chic %>%
  select(death, temp, dewpoint, pm10, o3) %>%
  corrr::correlate(diagonal = 1) %>%
  corrr::shave(upper = FALSE)

# 现在，我们使用{tidyr}包中的pivot_longer()函数将生成的矩阵以长格式表示:

corm <- corm %>%
  pivot_longer(
    cols = -term,
    names_to = "colname",
    values_to = "corr"
  ) %>%
  mutate(rowname = fct_inorder(term),
         colname = fct_inorder(colname))

# 作图，使用geom_tile()画heatmap，使用geom_text()添加标签:

ggplot(corm, aes(rowname, fct_rev(colname),
                 fill = corr)) +
  geom_tile() +
  geom_text(aes(label = round(corr, 2))) +
  coord_fixed() +
  labs(x = NULL, y = NULL)

# 这里使用一个发散的调色板，以0相关性为中心，用白色表示缺失的数据。
# 此外，热图周围没有网格线和填充，但有基于底层填充颜色的标签:

ggplot(corm, aes(rowname, fct_rev(colname),
                 fill = corr)) +
  geom_tile() +
  geom_text(aes(
    label = format(round(corr, 2), nsmall = 2),
    color = abs(corr) < .75
  )) +
  coord_fixed(expand = FALSE) +
  scale_color_manual(values = c("white", "black"),
                     guide = "none") +
  scale_fill_distiller(
    palette = "PuOr", na.value = "white",
    direction = 1, limits = c(-1, 1)
  ) +
  labs(x = NULL, y = NULL) +
  theme(panel.border = element_rect(color = NA, fill = NA),
        legend.position = c(.85, .8))


# 3. 创建等高线图
# 等高线图可以用来对数据分段，显示观测值的密度:
ggplot(chic, aes(temp, o3)) +
  geom_density_2d() +
  labs(x = "Temperature (°F)", x = "Ozone Level")

ggplot(chic, aes(temp, o3)) +
  geom_density_2d_filled(show.legend = FALSE) +
  coord_cartesian(expand = FALSE) +
  labs(x = "Temperature (°F)", x = "Ozone Level")

# 现在绘制三维数据，我们将绘制与温度和臭氧水平相关的露点阈值(即空气中的水汽将凝结成液体露珠的温度):

## interpolate data
library(akima)
fld <- with(chic, interp(x = temp, y = o3, z = dewpoint))

## prepare data in long format
library(reshape2)
df <- melt(fld$z, na.rm = TRUE)
names(df) <- c("x", "y", "Dewpoint")

g <- ggplot(data = df, aes(x = x, y = y, z = Dewpoint))  +
  labs(x = "Temperature (°F)", y = "Ozone Level",
       color = "Dewpoint")

g + stat_contour(aes(color = ..level.., fill = Dewpoint))

# 线条表示绘制露点的不同水平，但这不是一个漂亮的图，因为缺少边界，也很难阅读。
# 我们尝试使用绿色调色板来编码每个臭氧水平和温度组合的露点:
g + geom_tile(aes(fill = Dewpoint)) +
    scale_fill_viridis_c(option = "inferno")

# 如果我们用一个等高线图和一个瓦片图（tile）来填充等高线下面的区域，会是什么样子?
g + geom_tile(aes(fill = Dewpoint)) +
    stat_contour(color = "white", size = .7, bins = 5) +
    scale_fill_viridis_c()


# 4. 绘制热图
#   与我们的第一张等高线地图类似，
#   我们可以通过geom_hex()很容易地显示分块到六边形网格的点的频数或密度:
ggplot(chic, aes(temp, o3)) +
  geom_hex() +
  scale_fill_distiller(palette = "YlOrRd", direction = 1) +
  labs(x = "Temperature (°F)", y = "Ozone Level")

# 通常情况下，白线会出现在图中。你可以将颜色映射到count..(默认值)或..density.....
ggplot(chic, aes(temp, o3)) +
  geom_hex(aes(color = ..count..)) +
  scale_fill_distiller(palette = "YlOrRd", direction = 1) +
  scale_color_distiller(palette = "YlOrRd", direction = 1) +
  labs(x = "Temperature (°F)", y = "Ozone Level")

# 或为所有六边形单元格设置相同的边框颜色:
ggplot(chic, aes(temp, o3)) +
  geom_hex(color = "grey") +
  scale_fill_distiller(palette = "YlOrRd", direction = 1) +
  labs(x = "Temperature (°F)", y = "Ozone Level")

# 也可以修改默认的binning，以增加或者减少六边形单元格cell的数量:
ggplot(chic, aes(temp, o3, fill = ..density..)) +
  geom_hex(bins = 50, color = "grey") +
  scale_fill_distiller(palette = "YlOrRd", direction = 1) +
  labs(x = "Temperature (°F)", y = "Ozone Level")


# 5. 创建岭线图（Ridge）
# 虽然可以使用基本的ggplot2命令来创建，但更流行ggridge包，可以更容易创建这些图。
library(ggridges)
ggplot(chic, aes(x = temp, y = factor(year))) +
   geom_density_ridges(fill = "gray90") +
   labs(x = "Temperature (°F)", y = "Year")

# 可以通过分别使用参数rel_min_height和scale指定重叠和尾部。
# 此外，我们根据年份改变颜色，使其更有吸引力。
ggplot(chic, aes(x = temp, y = factor(year), fill = year)) +
  geom_density_ridges(alpha = .8, color = "white",
                      scale = 2.5, rel_min_height = .01) +
  labs(x = "Temperature (°F)", y = "Year") +
  guides(fill = FALSE) +
  theme_ridges()

# 还可以将缩放参数设置为小于1的值来消除重叠(但这在某种程度上与岭线图的想法相矛盾……)。
# 下面是一个使用翠绿色渐变和内置主题的例子:
ggplot(chic, aes(x = temp, y = season, fill = ..x..)) +
  geom_density_ridges_gradient(scale = .9, gradient_lwd = .5,
                               color = "black") +
  scale_fill_viridis_c(option = "plasma", name = "") +
  labs(x = "Temperature (°F)", y = "Season") +
  theme_ridges(font_family = "Roboto Condensed", grid = FALSE)

# 也可以对每个脊线里的几个组进行比较，并根据不同分组着色。

library(tidyverse)

## only plot extreme season using dplyr from the tidyverse
ggplot(data = filter(chic, season %in% c("Summer", "Winter")),
         aes(x = temp, y = year, fill = paste(year, season))) +
  geom_density_ridges(alpha = .7, rel_min_height = .01,
                      color = "white", from = -5, to = 95) +
  scale_fill_cyclical(breaks = c("1997 Summer", "1997 Winter"),
                      labels = c(`1997 Summer` = "Summer",
                                 `1997 Winter` = "Winter"),
                      values = c("tomato", "dodgerblue"),
                      name = "Season:", guide = "legend") +
  theme_ridges(grid = FALSE) +
  labs(x = "Temperature (°F)", y = "Year")

# 可以在ggridge包中的geom_density_ridge()命令中，使用stat = "binline"为不同的组创建直方图:
ggplot(chic, aes(x = temp, y = factor(year), fill = year)) +
  geom_density_ridges(stat = "binline", bins = 25, scale = .9,
                      draw_baseline = FALSE, show.legend = FALSE) +
  theme_minimal() +
  labs(x = "Temperature (°F)", y = "Season")
